package org.gap.wizards.creature;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.gap.wizards.combat.Attack;
import org.gap.wizards.combat.MeleeAttackChallenge;
import org.gap.wizards.items.Item;
import org.gap.wizards.items.effects.IncreaseAttribute;
import org.gap.wizards.pc.Skill;
import org.gap.wizards.pc.Skilled;
import org.gap.wizards.utils.Dice;
import org.gap.wizards.utils.Persistence;
import org.gap.wizards.world.Location;

public class Animal extends BaseCreature implements Skilled {
	private Map<String, Skill> skills;
	private Attack attack;
	private Brain brains;

	public Animal() {
		super();
	}
	
	public Animal(Brain brains, Description type, Attack clawAttack) {
		super(type);
		this.skills = new HashMap<String, Skill>();
		this.brains = brains;
		this.attack = clawAttack;
		
		brains.setCreature(this);
	}

	public void performWith(LocalWorldView worldView) {
		if (worldView.enemyIsNear() && !worldView.canMoveAwayFromEnemy()) {
			MeleeAttackChallenge action = new MeleeAttackChallenge(worldView.getEnemy(), this, attack);
			worldView.addAction(action);
		}
	}

	@Override
	public void addSkill(Skill skill) {
		skills.put(skill.getName(), skill);
	}

	@Override
	public Skill getSkill(String byName) {
		return skills.get(byName);
	}

	public Condition getCondition() {
		return getAttribute(Attribute.Hitpoints) == 0? Condition.Dead: Condition.Alive;
	}

	@Override
	public Collection<Item> dropAllItems() {
		Item item = new Item(new IncreaseAttribute(Attribute.Hunger, Dice.D6), null);
		return Arrays.<Item>asList(item);
	}
	
	@Override
	public void attack(Creature creature) {
		Skill skill = getSkill(attack.desiredSkillName());
		if (skill != null) {
			switch (skill.rollWithModifier(0)) {
				case SUCCESS:
					creature.decrease(Attribute.Hitpoints, attack.rollDamage());
					break;
				case FAILURE:
					// do nothing yet.
			}
		}
	}

	@Override
	public void update(Location location) {
		if (getAttribute(Attribute.Hitpoints) < 1) {
			location.removeCreature(this);
			Item corpse = AnimalFactory.createCorpse();
			location.addItemAt(getLocation(), corpse);
		} else {
			brains.update(location);
		}
	}
	
	@Override
	public boolean equals(Object obj) {
		if (obj == null || !obj.getClass().equals(Animal.class)) {
			return false;
		}
		Animal other = (Animal)obj;
		return brains.equals(other.brains) && super.equals(other);
	}
	
	@Override
	public void persist(Persistence persister) {
		super.persist(persister);
		persister.set("attack.class", attack.getClass());
		attack.persist(persister);

		persister.beginSection("ai");
		persister.set("class", brains.getClass());
		brains.persist(persister);
		persister.endSection();
	}
	
	@Override
	public void load(Persistence persister) {
		super.load(persister);
		attack = (Attack) persister.getClass("attack.class");
		attack.load(persister);
		
		persister.beginSection("ai");
		brains = (Brain) persister.getClass("class");
		brains.setCreature(this);
		brains.load(persister);
		persister.endSection();
	}
}
